package com.weiquan.service.impl;

import com.weiquan.exception.BusinessException;
import com.weiquan.service.FileUploadService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

/**
 * 文件上传服务实现类
 */
@Slf4j
@Service
public class FileUploadServiceImpl implements FileUploadService {

    @Value("${file.upload.path:/uploads}")
    private String uploadPath;

    @Value("${file.upload.domain:http://localhost:8080}")
    private String domain;

    @Value("${file.upload.max-size:10485760}") // 10MB
    private long maxFileSize;

    // 允许的图片类型
    private static final String[] IMAGE_TYPES = {
            "image/jpeg", "image/jpg", "image/png", "image/gif", "image/bmp", "image/webp"
    };

    // 允许的文档类型
    private static final String[] DOCUMENT_TYPES = {
            "application/pdf", "application/msword", 
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
            "application/vnd.ms-excel",
            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
            "text/plain"
    };

    // 允许的音频类型
    private static final String[] AUDIO_TYPES = {
            "audio/mpeg", "audio/wav", "audio/mp3", "audio/ogg"
    };

    // 允许的视频类型
    private static final String[] VIDEO_TYPES = {
            "video/mp4", "video/avi", "video/mov", "video/wmv"
    };

    @Override
    public String uploadFile(MultipartFile file, String category) {
        if (file == null || file.isEmpty()) {
            throw new BusinessException("文件不能为空");
        }

        // 验证文件大小
        if (!validateFileSize(file, maxFileSize)) {
            throw new BusinessException("文件大小不能超过10MB");
        }

        // 根据分类验证文件类型
        String[] allowedTypes = getAllowedTypesByCategory(category);
        if (!validateFileType(file, allowedTypes)) {
            throw new BusinessException("不支持的文件类型");
        }

        try {
            // 生成唯一文件名
            String fileName = generateUniqueFileName(file.getOriginalFilename());
            
            // 创建目录结构：category/yyyy/MM/dd/
            String datePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
            String relativePath = category + "/" + datePath + "/" + fileName;
            
            // 创建完整的文件路径
            Path fullPath = Paths.get(uploadPath, relativePath);
            
            // 确保目录存在
            Files.createDirectories(fullPath.getParent());
            
            // 保存文件
            file.transferTo(fullPath.toFile());
            
            log.info("文件上传成功：{}", relativePath);
            
            // 返回访问URL
            return domain + "/uploads/" + relativePath.replace("\\", "/");
            
        } catch (IOException e) {
            log.error("文件上传失败", e);
            throw new BusinessException("文件上传失败");
        }
    }

    @Override
    public List<String> uploadFiles(List<MultipartFile> files, String category) {
        if (files == null || files.isEmpty()) {
            throw new BusinessException("文件列表不能为空");
        }

        List<String> uploadedUrls = new ArrayList<>();
        
        for (MultipartFile file : files) {
            try {
                String url = uploadFile(file, category);
                uploadedUrls.add(url);
            } catch (Exception e) {
                log.error("批量上传文件失败：{}", file.getOriginalFilename(), e);
                // 继续上传其他文件，不中断整个过程
            }
        }

        if (uploadedUrls.isEmpty()) {
            throw new BusinessException("所有文件上传失败");
        }

        return uploadedUrls;
    }

    @Override
    public boolean deleteFile(String fileUrl) {
        if (!StringUtils.hasText(fileUrl)) {
            return false;
        }

        try {
            // 从URL中提取相对路径
            String relativePath = fileUrl.replace(domain + "/uploads/", "");
            Path filePath = Paths.get(uploadPath, relativePath);
            
            if (Files.exists(filePath)) {
                Files.delete(filePath);
                log.info("文件删除成功：{}", relativePath);
                return true;
            } else {
                log.warn("要删除的文件不存在：{}", relativePath);
                return false;
            }
            
        } catch (IOException e) {
            log.error("文件删除失败：{}", fileUrl, e);
            return false;
        }
    }

    @Override
    public String getFileUrl(String fileName) {
        if (!StringUtils.hasText(fileName)) {
            return null;
        }
        
        return domain + "/uploads/" + fileName;
    }

    @Override
    public boolean validateFileType(MultipartFile file, String[] allowedTypes) {
        if (file == null || allowedTypes == null || allowedTypes.length == 0) {
            return false;
        }

        String contentType = file.getContentType();
        if (!StringUtils.hasText(contentType)) {
            return false;
        }

        return Arrays.asList(allowedTypes).contains(contentType.toLowerCase());
    }

    @Override
    public boolean validateFileSize(MultipartFile file, long maxSize) {
        if (file == null) {
            return false;
        }
        
        return file.getSize() <= maxSize;
    }

    @Override
    public String generateUniqueFileName(String originalFileName) {
        if (!StringUtils.hasText(originalFileName)) {
            return UUID.randomUUID().toString();
        }

        // 获取文件扩展名
        String extension = "";
        int lastDotIndex = originalFileName.lastIndexOf(".");
        if (lastDotIndex > 0 && lastDotIndex < originalFileName.length() - 1) {
            extension = originalFileName.substring(lastDotIndex);
        }

        // 生成UUID + 扩展名
        return UUID.randomUUID().toString() + extension;
    }

    /**
     * 根据分类获取允许的文件类型
     */
    private String[] getAllowedTypesByCategory(String category) {
        if (!StringUtils.hasText(category)) {
            // 默认允许图片和文档
            List<String> allTypes = new ArrayList<>();
            allTypes.addAll(Arrays.asList(IMAGE_TYPES));
            allTypes.addAll(Arrays.asList(DOCUMENT_TYPES));
            return allTypes.toArray(new String[0]);
        }

        switch (category.toLowerCase()) {
            case "image":
            case "avatar":
            case "photo":
                return IMAGE_TYPES;
            case "document":
            case "file":
            case "evidence":
                return DOCUMENT_TYPES;
            case "audio":
            case "voice":
                return AUDIO_TYPES;
            case "video":
                return VIDEO_TYPES;
            case "all":
                List<String> allTypes = new ArrayList<>();
                allTypes.addAll(Arrays.asList(IMAGE_TYPES));
                allTypes.addAll(Arrays.asList(DOCUMENT_TYPES));
                allTypes.addAll(Arrays.asList(AUDIO_TYPES));
                allTypes.addAll(Arrays.asList(VIDEO_TYPES));
                return allTypes.toArray(new String[0]);
            default:
                return IMAGE_TYPES; // 默认只允许图片
        }
    }

    /**
     * 获取文件类型描述
     */
    public String getFileTypeDescription(String category) {
        switch (category.toLowerCase()) {
            case "image":
            case "avatar":
            case "photo":
                return "支持JPG、PNG、GIF、BMP、WebP格式";
            case "document":
            case "file":
            case "evidence":
                return "支持PDF、Word、Excel、TXT格式";
            case "audio":
            case "voice":
                return "支持MP3、WAV、OGG格式";
            case "video":
                return "支持MP4、AVI、MOV、WMV格式";
            case "all":
                return "支持图片、文档、音频、视频格式";
            default:
                return "支持常见文件格式";
        }
    }

    /**
     * 获取文件大小的友好显示
     */
    public String getFileSizeDisplay(long size) {
        if (size < 1024) {
            return size + " B";
        } else if (size < 1024 * 1024) {
            return String.format("%.1f KB", size / 1024.0);
        } else if (size < 1024 * 1024 * 1024) {
            return String.format("%.1f MB", size / (1024.0 * 1024.0));
        } else {
            return String.format("%.1f GB", size / (1024.0 * 1024.0 * 1024.0));
        }
    }

    /**
     * 清理过期文件（可以定时执行）
     */
    public void cleanExpiredFiles(int daysToKeep) {
        // 这里可以实现清理逻辑
        // 删除超过指定天数的临时文件
        log.info("开始清理{}天前的过期文件", daysToKeep);
        
        try {
            Path uploadDir = Paths.get(uploadPath);
            if (Files.exists(uploadDir)) {
                // 遍历文件夹，删除过期文件
                // 具体实现可以根据需要添加
            }
        } catch (Exception e) {
            log.error("清理过期文件失败", e);
        }
    }
}